// gorpc/protocol/header.go

package protocol

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"gorpc/common"
	"io"
)

type Header struct {
	// 固定头字段（总长度16字节）
	Magic      uint16 // 协议标识 *
	Version    uint8  // 协议版本 *
	Flags      uint8  // 标志位 *
	MethodLen  uint16 // 方法名长度 *
	Seq        uint64 // 请求序号
	ErrorLen   uint16 // 错误信息长度 *
	BodyLength uint32 // 消息体长度

	// 变长字段（根据上述长度解析）
	ServiceMethod string
	Error         string
}

const (
	FixedHeaderSize = 20 // 2+1+1+2+8+2+4 = 20? 需要确认实际长度
	MagicNumber     = uint16(0xEFEF)
	ProtocolVersion = uint8(1)
)

func NewHeader(ServiceMethod string) *Header {
	return &Header{
		Magic:         MagicNumber,
		Version:       ProtocolVersion,
		Flags:         0,
		MethodLen:     uint16(len(ServiceMethod)),
		Seq:           0,
		ErrorLen:      0,
		BodyLength:    0,
		ServiceMethod: ServiceMethod,
	}
}

func (h *Header) Encode(w io.Writer) error {
	h.MethodLen = uint16(len(h.ServiceMethod))
	if err := h.encodeFixedHeader(w); err != nil {
		return err
	}
	if err := h.encodeVariableFields(w); err != nil {
		return err
	}
	return nil
}

// encodeFixedHeader 编码到二进制
func (h *Header) encodeFixedHeader(w io.Writer) error {
	data := []interface{}{
		MagicNumber,
		ProtocolVersion,
		h.Flags,
		h.MethodLen,
		h.Seq,
		h.ErrorLen,
		h.BodyLength,
	}

	for _, v := range data {
		if err := binary.Write(w, binary.BigEndian, v); err != nil {
			return err
		}
	}

	return nil
}

func (h *Header) encodeVariableFields(w io.Writer) error {
	// 校验数据一致性
	if int(h.MethodLen) != len(h.ServiceMethod) {
		return fmt.Errorf("方法名长度不一致: 协议头声明 %d 实际 %d",
			h.MethodLen, len(h.ServiceMethod))
	}

	if int(h.ErrorLen) != len(h.Error) {
		return fmt.Errorf("错误信息长度不一致: 协议头声明 %d 实际 %d",
			h.ErrorLen, len(h.Error))
	}

	// 批量写入变长字段
	if _, err := w.Write([]byte(h.ServiceMethod)); err != nil {
		return fmt.Errorf("写入方法名失败: %w", err)
	}

	if _, err := w.Write([]byte(h.Error)); err != nil {
		return fmt.Errorf("写入错误信息失败: %w", err)
	}

	return nil
}

func (h *Header) Decode(r io.Reader) error {
	// 1. 读取固定协议头
	fixedHeader := make([]byte, FixedHeaderSize)
	if _, err := io.ReadFull(r, fixedHeader); err != nil {
		err := fmt.Errorf("读取固定头失败: %w", err)
		return err
	}

	// 2. 解析固定头字段
	if err := h.decodeFixedHeader(fixedHeader); err != nil {
		return fmt.Errorf("解析固定头失败: %w", err)
	}

	// 3. 读取变长字段
	variableData := make([]byte, h.totalVariableSize())
	if _, err := io.ReadFull(r, variableData); err != nil {
		return fmt.Errorf("读取变长数据失败: %w", err)
	}

	// 4. 解析变长字段
	if err := h.decodeVariableFields(bytes.NewReader(variableData)); err != nil {
		return fmt.Errorf("解析变长字段失败: %w", err)
	}

	if h.Magic != MagicNumber {
		return common.NewRPCError(
			common.ErrorCodeFramework,
			"invalid magic number",
			nil)
	}

	if h.Version > ProtocolVersion {
		return common.NewRPCError(
			common.ErrorCodeFramework,
			"unsupported protocol version",
			nil)
	}
	return nil
}

func (h *Header) decodeFixedHeader(data []byte) error {
	fixed := struct {
		Magic      uint16
		Version    uint8
		Flags      uint8
		MethodLen  uint16
		Seq        uint64
		ErrorLen   uint16
		BodyLength uint32
	}{}

	// 反序列化到结构体
	if err := binary.Read(
		bytes.NewReader(data),
		binary.BigEndian,
		&fixed, // 注意这里传递结构体指针
	); err != nil {
		return err
	}
	h.Magic = fixed.Magic
	h.Version = fixed.Version
	h.Flags = fixed.Flags
	h.MethodLen = fixed.MethodLen
	h.Seq = fixed.Seq
	h.ErrorLen = fixed.ErrorLen
	h.BodyLength = fixed.BodyLength
	return nil
}

// totalVariableSize Decode 从二进制解码
func (h *Header) totalVariableSize() int {
	return int(h.MethodLen) + int(h.ErrorLen)
}

func (h *Header) decodeVariableFields(r io.Reader) error {
	// 读取方法名
	methodBuf := make([]byte, h.MethodLen)
	if _, err := io.ReadFull(r, methodBuf); err != nil {
		return err
	}
	h.ServiceMethod = string(methodBuf)

	// 读取错误信息
	errorBuf := make([]byte, h.ErrorLen)
	if _, err := io.ReadFull(r, errorBuf); err != nil {
		return err
	}
	h.Error = string(errorBuf)
	return nil
}
